package com.controller;

import com.annotation.IgnoreAuth;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.entity.ConfigEntity;
import com.entity.EIException;
import com.service.ConfigService;
import com.utils.R;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.Date;

/**
 * 上传文件映射表
 */
@RestController
@RequestMapping("file")
@SuppressWarnings({"unchecked", "rawtypes"})
public class FileController {
    @Autowired
    private ConfigService configService;

    /**
     * 上传文件
     * 此方法处理文件上传请求。它首先检查上传的文件是否为空，
     * 然后获取文件扩展名，准备上传目录，生成文件名并将文件保存到指定位置。
     * 如果指定的type参数为"1"，则更新或插入配置表中的faceFile配置项。
     * 最后，返回上传文件的文件名。
     * @param file 待上传的文件
     * @param type 文件类型标识符
     * @return 包含上传文件名的响应对象
     * @throws Exception 如果上传过程中发生错误
     */
    @RequestMapping("/upload")
    public R upload(@RequestParam("file") MultipartFile file, String type) throws Exception {
        // 检查上传的文件是否为空
        if (file.isEmpty()) {
            throw new EIException("上传文件不能为空");
        }
        // 获取文件扩展名
        String fileExt = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
        // 获取上传文件的保存目录
        File path = new File(ResourceUtils.getURL("classpath:static").getPath());
        if (!path.exists()) {
            path = new File("");
        }
        File upload = new File(path.getAbsolutePath(), "/upload/");
        // 如果上传目录不存在，则创建
        if (!upload.exists()) {
            upload.mkdirs();
        }
        // 生成新的文件名，使用当前时间戳加文件扩展名
        String fileName = new Date().getTime() + "." + fileExt;
        File dest = new File(upload.getAbsolutePath() + "/" + fileName);
        // 将上传的文件保存到指定位置
        file.transferTo(dest);
        // 如果type为"1"，则更新或插入配置表中的faceFile配置项
        if (StringUtils.isNotBlank(type) && type.equals("1")) {
            ConfigEntity configEntity = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "faceFile"));
            if (configEntity == null) {
                configEntity = new ConfigEntity();
                configEntity.setName("faceFile");
                configEntity.setValue(fileName);
            } else {
                configEntity.setValue(fileName);
            }
            configService.insertOrUpdate(configEntity);
        }
        // 返回上传文件的文件名
        return R.ok().put("file", fileName);
    }

    /**
     * 下载文件
     * 此方法用于下载指定的文件。它首先定位到类路径下的静态资源目录，
     * 然后构建到上传文件目录的路径。如果所需的目录不存在，它会尝试创建这些目录。
     * 如果请求的文件存在，则准备将其作为字节流返回，并设置适当的HTTP头信息，
     * 指定下载行为。如果文件不存在或发生IO异常，则返回一个表示内部服务器错误的响应。
     */
    @IgnoreAuth
    @RequestMapping("/download")
    public ResponseEntity<byte[]> download(@RequestParam String fileName) {
        try {
            // 初始化文件路径对象，指向类路径下的static目录
            File path = new File(ResourceUtils.getURL("classpath:static").getPath());
            // 如果static目录不存在，则创建
            if (!path.exists()) {
                path = new File("");
            }
            // 构建上传目录的文件路径对象
            File upload = new File(path.getAbsolutePath(), "/upload/");
            // 如果上传目录不存在，则创建
            if (!upload.exists()) {
                upload.mkdirs();
            }
            // 构建最终文件路径，包括文件名
            File file = new File(upload.getAbsolutePath() + "/" + fileName);
            // 如果文件存在，则准备下载
            if (file.exists()) {
	            /*
	            // 检查当前用户是否有权读取该文件，若无权则返回403错误
	            if(!fileService.canRead(file, SessionManager.getSessionUser())){
	                getResponse().sendError(403);
	            }
	            */
                // 设置HTTP响应头信息，指定返回的内容类型为字节流，并且以附件形式下载，文件名为原文件名
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
                headers.setContentDispositionFormData("attachment", fileName);
                // 读取文件内容为字节流，并与设置好的响应头一起返回
                return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
            }
        } catch (IOException e) {
            e.printStackTrace(); // 输出异常信息到控制台
        }
        // 如果文件不存在或发生异常，返回表示内部服务器错误的响应
        return new ResponseEntity<byte[]>(HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
